package com.atguigu.lease.web.admin.service.impl;

import com.atguigu.lease.common.exception.HasRoomException;
import com.atguigu.lease.common.result.ResultCodeEnum;
import com.atguigu.lease.model.entity.*;
import com.atguigu.lease.model.enums.ExceptionEnum;
import com.atguigu.lease.model.enums.ItemType;
import com.atguigu.lease.web.admin.mapper.*;
import com.atguigu.lease.web.admin.service.*;
import com.atguigu.lease.web.admin.vo.apartment.ApartmentDetailVo;
import com.atguigu.lease.web.admin.vo.apartment.ApartmentItemVo;
import com.atguigu.lease.web.admin.vo.apartment.ApartmentQueryVo;
import com.atguigu.lease.web.admin.vo.apartment.ApartmentSubmitVo;
import com.atguigu.lease.web.admin.vo.fee.FeeValueVo;
import com.atguigu.lease.web.admin.vo.graph.GraphVo;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.google.common.graph.Graph;
import jakarta.annotation.Resource;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;

import java.util.List;
import java.util.stream.Collectors;

/**
 * @author liubo
 * @description 针对表【apartment_info(公寓信息表)】的数据库操作Service实现
 * @createDate 2023-07-24 15:48:00
 */


// TODO:这里使用了map，Steam流


@Service
public class ApartmentInfoServiceImpl extends ServiceImpl<ApartmentInfoMapper, ApartmentInfo>
        implements ApartmentInfoService {


    @Resource
    private ApartmentInfoMapper apartmentInfoMapper;

    @Resource
    private ApartmentFacilityService apartmentFacilityService;

    @Resource
    private ApartmentLabelService apartmentLabelService;

    @Resource
    private ApartmentFeeValueService apartmentFeeValueService;

    @Resource
    private GraphInfoService graphInfoService;

    @Resource
    private GraphInfoMapper graphInfoMapper;

    @Resource
    private LabelInfoMapper labelInfoMapper;

    @Resource
    private FacilityInfoMapper facilityInfoMapper;

    @Resource
    private FeeValueMapper feeValueMapper;

    @Resource
    private RoomInfoMapper roomInfoMapper;

    @Override
    public IPage<ApartmentItemVo> pageFind(IPage<ApartmentItemVo> page, ApartmentQueryVo queryVo) {
        IPage<ApartmentItemVo> list = apartmentInfoMapper.pageFind(page, queryVo);
        return list;
    }

    @Override
    public ApartmentDetailVo getDetailById(Long id) {

        // 解决一个报错问题，是因为xml中注释中的占位符也会被算上
        ApartmentDetailVo apartmentDetailVo = new ApartmentDetailVo();
        // - 查询公寓信息
        /*
         * 公寓的信息能够直接查出来
         * 然后利用spring提供的BeanUitls进行拷贝
         * */
        ApartmentInfo apartmentInfo = super.getById(id);


        // - 查询公寓对应的图片信息列表
        /*
         * 需要哪些条件，第一是图片所属公寓的Id，还有就是所属的类型
         * 第一种方法是先查出来图片的所用信息，然后通过stream流进行组装
         * 优点熟悉java的话好理解，但是代码量多，java代码复杂
         * 添加到vo中
         * 第二中方法手写mapper，直接查出来graphvo
         * 有点是代码量少，缺点要写sql
         * java代码量少点较好
         * */
/*        LambdaQueryWrapper<GraphInfo> graphInfoQueryWrapper = new LambdaQueryWrapper<>();
        graphInfoQueryWrapper
                .eq(GraphInfo::getItemType, ItemType.APARTMENT)
                .eq(GraphInfo::getItemId, id);

        List<GraphInfo> graphInfos = graphInfoMapper.selectList(graphInfoQueryWrapper);

        List<GraphVo> graphVoList = graphInfos.stream().map(graphInfo -> GraphVo.builder()
                .name(graphInfo.getName())
                .url(graphInfo.getUrl())
                .build()).toList();


        apartmentDetailVo.setGraphVoList(graphVoList);*/
        List<GraphVo> graphVoList = graphInfoMapper.selectGraphVoList(id,ItemType.APARTMENT);

        // - 查询公寓对应的标签列表
        // 我有公寓id，拿着公寓id去查标签id，然后拿着很多标签id去查对应的标签名和标签类型
        List<LabelInfo> labelInfoList = labelInfoMapper.selectLabelInfolistByAid(id);

        // - 查询公寓对应的配套设备列表
        List<FacilityInfo> facilityInfoList = facilityInfoMapper.selectFacilityInfolistByAid(id);

        // - 查询公寓配套的杂费值列表
        List<FeeValueVo> feeValueVoList = feeValueMapper.selectFeeValueVolistByAid(id);

        BeanUtils.copyProperties(apartmentInfo, apartmentDetailVo);
        apartmentDetailVo.setGraphVoList(graphVoList);
        apartmentDetailVo.setLabelInfoList(labelInfoList);
        apartmentDetailVo.setFacilityInfoList(facilityInfoList);
        apartmentDetailVo.setFeeValueVoList(feeValueVoList);


        return apartmentDetailVo;
    }


    // TODO：这里有更详细的全局异常处理
    @Override
    public void removeByIdAndRemind(Long id) {
        //通过公寓id去查公寓下面还有没有房间，意思就是看看房间的数量是不是0
        LambdaQueryWrapper<RoomInfo> roomInfoQueryWrapper = new LambdaQueryWrapper<>();
        roomInfoQueryWrapper.eq(RoomInfo::getApartmentId,id);
        Long roomNumber = roomInfoMapper.selectCount(roomInfoQueryWrapper);

        if (0 < roomNumber){
            //这个智能传入字符串我想传入错误编码和错误的文字，这个就不满足我的去求，所以我们需要进行更详细的异常
//            throw new RuntimeException("还有房间");
            throw new HasRoomException(ResultCodeEnum.ADMIN_APARTMENT_DELETE_ERROR);
            //我们就像能不能注解传入ExceptionEnum
        }

        apartmentInfoMapper.selectById(id);
        //还要删除和他关联的数据

    }


    //service实现类中实现逻辑

    /***
     * 保存和更新放在一起了，步骤稍微复杂一点
     * @param apartmentSubmitVo
     */
    @Override
    public void saveOrUpdateByVo(ApartmentSubmitVo apartmentSubmitVo) {
        // 1. 首先第一个我们需要判断apartmentSubmitVo中是否有id
        boolean existId = apartmentSubmitVo.getId() != null;

        // 2. 我们已经判断出了id是否存在了，首先把不需要先删除在更新的操作完成，也就是ApartmentInfo的信息的添加和更新
        super.saveOrUpdate(apartmentSubmitVo); //因为 apartmentSubmitVo 是继承了 ApartmentInfo的所以可以直接传入

        // *在修改的时候我们的逻辑是先删除在添加，所以添加的操作始终是要实现的*
        if (existId) { //apartmentSubmitVo数据存在

            // - 删除公寓配套信息 ：在公寓-配套关秀表中，删除公寓id与配套id对应的项
            LambdaQueryWrapper<ApartmentFacility> facilityQueryWrapper = new LambdaQueryWrapper<>();
            facilityQueryWrapper
                    // 就是说配套关系中，公寓id对应的全部删除
                    .eq(ApartmentFacility::getApartmentId, apartmentSubmitVo.getId());
            apartmentFacilityService.remove(facilityQueryWrapper);


            // - 删除公寓标签信息
            LambdaQueryWrapper<ApartmentLabel> apartmentQueryWrapper = new LambdaQueryWrapper<>();
            apartmentQueryWrapper
                    .eq(ApartmentLabel::getApartmentId, apartmentSubmitVo.getId());
            apartmentLabelService.remove(apartmentQueryWrapper);


            // - 删除公寓杂费值信息
            LambdaQueryWrapper<ApartmentFeeValue> apartmentFeeValueQueryWrapper = new LambdaQueryWrapper<>();
            apartmentFeeValueQueryWrapper
                    .eq(ApartmentFeeValue::getApartmentId, apartmentSubmitVo.getId());
            apartmentFeeValueService.remove(apartmentFeeValueQueryWrapper);


            // - 删除公寓图片信息
            LambdaQueryWrapper<GraphInfo> graphInfoQueryWrapper = new LambdaQueryWrapper<>();
            graphInfoQueryWrapper
                    .eq(GraphInfo::getItemId, apartmentSubmitVo.getId())
                    .eq(GraphInfo::getItemType, ItemType.APARTMENT);
            graphInfoService.remove(graphInfoQueryWrapper);


        }

        // - 填加公寓配套id，添加实体类，所以我们需要自己构造实体类


        List<ApartmentFacility> apartmentFacilityList = apartmentSubmitVo.getFacilityInfoIds().stream().map(id -> ApartmentFacility.builder()
                .apartmentId(apartmentSubmitVo.getId())
                .facilityId(id)
                .build()).toList();
        apartmentFacilityService.saveBatch(apartmentFacilityList);


        // - 填加公寓标签id
        List<ApartmentLabel> apartmentLabelList = apartmentSubmitVo.getLabelIds().stream().map(id -> ApartmentLabel.builder()
                .apartmentId(apartmentSubmitVo.getId())
                .labelId(id)
                .build()).toList();
        apartmentLabelService.saveBatch(apartmentLabelList);


        // - 填加公寓杂费值id
        List<ApartmentFeeValue> apartmentFeeValueList = apartmentSubmitVo.getFeeValueIds().stream().map(id -> ApartmentFeeValue.builder()
                .apartmentId(apartmentSubmitVo.getId())
                .feeValueId(id)
                .build()).toList();
        apartmentFeeValueService.saveBatch(apartmentFeeValueList);


        // - 填加公寓图片地址
        List<GraphInfo> graphInfoList = apartmentSubmitVo.getGraphVoList().stream().map(graphVo -> GraphInfo.builder()
                .url(graphVo.getUrl())
                .itemId(apartmentSubmitVo.getId())
                .itemType(ItemType.APARTMENT)
                .name(graphVo.getName())
                .build()).toList();
        graphInfoService.saveBatch(graphInfoList);
    }
}




